package org.springblade.thingsphere.manage.controller;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.excel.util.ExcelUtil;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.oss.model.BladeFile;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.constant.BladeConstant;
import org.springblade.core.tool.constant.RoleConstant;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.system.pojo.entity.Dict;
import org.springblade.thingsphere.CompositeProtocolSupport;
import org.springblade.thingsphere.manage.excel.ProtocolExcel;
import org.springblade.thingsphere.manage.pojo.entity.ProtocolEntity;
import org.springblade.thingsphere.manage.pojo.vo.ProtocolVO;
import org.springblade.thingsphere.manage.service.IProtocolService;
import org.springblade.thingsphere.manage.wrapper.ProtocolWrapper;
import org.springblade.thingsphere.network.protocol.impl.ProtocolAssetSupplier;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 协议管理 控制器
 *
 * @author lhb
 * @since 2024-09-26
 */
@RestController
@AllArgsConstructor
@RequestMapping("blade-protocol/protocol")
@Tag(name = "协议管理", description = "协议管理接口")
public class ProtocolController extends BladeController {

	private final IProtocolService protocolService;
	private final ProtocolAssetSupplier protocolAssetSupplier;

	@GetMapping("/dictionary")
	@ApiOperationSupport(order = 8)
	@Operation(summary = "获取字典", description = "获取字典")
	public R<List<Dict>> dictionary(String code) {
		List<Dict> tree = new ArrayList<>();
		List<ProtocolEntity> list = protocolService.list(Wrappers.<ProtocolEntity>lambdaQuery()
			.eq(ProtocolEntity::getStatus, 1)
		);
		for (ProtocolEntity protocol : list) {
			Dict dict = new Dict();
			dict.setId(protocol.getId());
			dict.setDictKey(StrUtil.toString(protocol.getId()));
			dict.setDictValue(protocol.getName());
			tree.add(dict);
		}
		return R.data(tree);
	}

	@GetMapping("/transportDict")
	@ApiOperationSupport(order = 8)
	@Operation(summary = "获取字典", description = "获取字典")
	public R<List<Dict>> transportDict(Long id) {
		List<Dict> tree = new ArrayList<>();
		CompositeProtocolSupport compositeProtocolSupport = protocolAssetSupplier.getProtocolSupportById(id);
		Set<String> strings = compositeProtocolSupport.getMessageCodecSupports().keySet();
		for (String string : strings) {
			Dict dict = new Dict();
			dict.setDictKey(string);
			dict.setDictValue(string);
			tree.add(dict);
		}
		return R.data(tree);
	}

	/**
	 * 协议管理 详情
	 */
	@GetMapping("/detail")
	@ApiOperationSupport(order = 1)
	@Operation(summary = "详情", description = "传入protocol")
	public R<ProtocolVO> detail(ProtocolEntity protocol) {
		ProtocolEntity detail = protocolService.getOne(Condition.getQueryWrapper(protocol));
		return R.data(ProtocolWrapper.build().entityVO(detail));
	}

	/**
	 * 协议管理 分页
	 */
	@GetMapping("/list")
	@ApiOperationSupport(order = 2)
	@Operation(summary = "分页", description = "传入protocol")
	public R<IPage<ProtocolVO>> list(@Parameter(hidden = true) @RequestParam Map<String, Object> protocol, Query query) {
		IPage<ProtocolEntity> pages = protocolService.page(Condition.getPage(query), Condition.getQueryWrapper(protocol, ProtocolEntity.class));
		return R.data(ProtocolWrapper.build().pageVO(pages));
	}

	/**
	 * 协议管理 新增或修改
	 */
	@PostMapping("/submit")
	@ApiOperationSupport(order = 6)
	@Operation(summary = "新增或修改", description = "传入protocol")
	public R submit(@Valid @RequestBody ProtocolEntity protocol) {

		if (null != protocol.getId()) {
			ProtocolEntity protocolOne = protocolService.getById(protocol.getId());
			if (1 == protocolOne.getStatus()) {
				throw new ServiceException("协议已发布不可修改, 请先停用");
			}
		}

		protocol.setStatus(0);
		protocolService.dictClear();
		return R.status(protocolService.saveOrUpdate(protocol));
	}

	/**
	 * 协议管理 删除
	 */
	@PostMapping("/remove")
	@ApiOperationSupport(order = 7)
	@Operation(summary = "逻辑删除", description = "传入ids")
	public R remove(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
		protocolService.dictClear();
		return R.status(protocolService.deleteLogic(Func.toLongList(ids)));
	}

	/**
	 * 导出数据
	 */
	@PreAuth(RoleConstant.HAS_ROLE_ADMIN)
	@GetMapping("/export-protocol")
	@ApiOperationSupport(order = 9)
	@Operation(summary = "导出数据", description = "传入protocol")
	public void exportProtocol(@Parameter(hidden = true) @RequestParam Map<String, Object> protocol, BladeUser bladeUser, HttpServletResponse response) {
		QueryWrapper<ProtocolEntity> queryWrapper = Condition.getQueryWrapper(protocol, ProtocolEntity.class);
		//if (!AuthUtil.isAdministrator()) {
		//	queryWrapper.lambda().eq(Protocol::getTenantId, bladeUser.getTenantId());
		//}
		queryWrapper.lambda().eq(ProtocolEntity::getIsDeleted, BladeConstant.DB_NOT_DELETED);
		List<ProtocolExcel> list = protocolService.exportProtocol(queryWrapper);
		ExcelUtil.export(response, "协议管理数据" + DateUtil.time(), "协议管理数据表", list, ProtocolExcel.class);
	}

	/**
	 * 上传协议包
	 *
	 * @param file
	 * @return
	 */
	@PostMapping("/put-file")
	public R<BladeFile> putFile(@RequestParam MultipartFile file) {
		return R.data(protocolService.putFile(file));
	}

	/**
	 * 发布 (加载jar文件到虚拟机)
	 */
	@PostMapping("/publish")
	public R<Boolean> publish(@Valid @RequestBody ProtocolEntity protocol) {
		return protocolService.publish(protocol);
	}

	/**
	 * 取消发布 (卸载jar文件)
	 */
	@PostMapping("/unpublish")
	public R<Boolean> unpublish(@Valid @RequestBody ProtocolEntity protocol) {
		return protocolService.unpublish(protocol);
	}
}
